import pandas as pd
import openpyxl
from openpyxl.styles import PatternFill
import os
import sys
import pathlib
import pandas as pd
import numpy as np

def split_and_compare_excel(file_path, split_field, compare_field, log_func=print):
    """
    将Excel或CSV文件按照指定字段拆分为两个sheet，并比对相同ID的记录，标记不同的单元格
    
    参数:
        file_path (str): Excel或CSV文件路径
        split_field (str): 用于拆分数据的字段名
        compare_field (str): 用于比对的字段名（如ID）
    """
   
    # 读取Excel或CSV文件
    log_func(f"正在读取文件: {file_path}")
    file_ext = pathlib.Path(file_path).suffix.lower()
    
    if file_ext in ['.csv']:
        df = pd.read_csv(file_path, dtype=str)  # 将所有列读取为字符串类型
        # 尝试将数值列转换为数值类型
        for col in df.columns:
            try:
                df[col] = pd.to_numeric(df[col])
            except ValueError:
                pass
    else:  # 默认作为Excel处理
        df = pd.read_excel(file_path)
    
    log_func(f"文件读取完成，共 {len(df)} 行数据")
    
    # 检查字段是否存在
    if split_field not in df.columns:
        log_func(f"错误: 拆分字段 '{split_field}' 不存在于Excel文件中")
        return False
    
    if compare_field not in df.columns:
        log_func(f"错误: 比对字段 '{compare_field}' 不存在于Excel文件中")
        return False
    
    # 获取拆分字段的唯一值
    unique_values = df[split_field].unique()
    
    if len(unique_values) != 2:
        log_func(f"警告: 拆分字段 '{split_field}' 应该有两个唯一值，但找到了 {len(unique_values)} 个值")
        if len(unique_values) < 2:
            log_func("错误: 至少需要两个不同的值来拆分数据")
            return False
        log_func(f"将使用前两个值: {unique_values[0]} 和 {unique_values[1]}")
        unique_values = unique_values[:2]
    
    arr=[]  #记录需要改变单元格底色的行列号和颜色
    colors = ['FF0000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', '00FFFF']
    last_color = None
    idx=0  #用于记录行号，如果当前行和下一行的比对字段值相同，则将当前行的比对字段值+1
    lg=len(df) 
    for dx in range(lg-1):
        if idx!=dx:
            continue
        row=df.iloc[dx]
        row_next=df.iloc[dx+1]
        
        if row[compare_field] == row_next[compare_field]:
            log_func(f'开始对比:{dx+1},{dx+2}')
        
            #print(dx,dx+1,row[compare_field],row_next[compare_field])
            idx=dx+1
            for x,i in enumerate(df.columns):

                if pd.isna(row[i]) and pd.isna(row_next[i]):
                    continue
                if  row[i]!= row_next[i]:
                    log_func(f"第{dx+2}行，第{x}列，字段{i}，值:{[row[i],row_next[i]]}")
                    # 生成不重复的随机颜色
                    while True:
                        color = np.random.choice(colors)
                        if color != last_color:
                            break
                    arr.append([dx+2,x+1,color])
                    arr.append([idx+2,x+1,color])
                    last_color = color
                   
                
            
        idx=idx+1

        
        
    # 创建填充样式列表
    fills = {color: PatternFill(start_color=color, end_color=color, fill_type='solid') for color in colors}

    # 禁用自动计算以优化性能
    workbook = openpyxl.load_workbook(file_path)
    workbook.calculation.full_recalc_on_load = False

    # 获取第一个工作表
    sheet = workbook.worksheets[0]
    # 标记不同单元格
    for cell_pos in arr:
        row, col, color = cell_pos
        log_func(f"标记单元格: 行{cell_pos[0]}，列{cell_pos[1]}，颜色{cell_pos[2]}")
        sheet.cell(row=row, column=col).fill = fills[color]

    # 保存并恢复自动计算
    workbook.calculation.full_recalc_on_load = True
    workbook.save(file_path)
    
    
    return True





def main():
    """
    主函数，处理命令行参数并执行比对
    """
    if len(sys.argv) != 4:
        print("用法: python excel_comparator.py <Excel文件路径> <拆分字段> <比对字段>")
        print("示例: python excel_comparator.py data.xlsx 类型 ID")
        return
    
    file_path = sys.argv[1]
    split_field = sys.argv[2]
    compare_field = sys.argv[3]
    
    if not os.path.exists(file_path):
        print(f"错误: 文件 '{file_path}' 不存在")
        return
    
    split_and_compare_excel(file_path, split_field, compare_field)

if __name__ == "__main__":
    main()